package com.jt.www.biz.order_pc.service.impl;

import com.alibaba.fastjson.JSON;
import com.jt.www.admin.order_pc.service.ExtendService;
import com.jt.www.biz.order_pc.service.InsService;
import com.jt.www.biz.pay.service.PayOutService;
import com.jt.www.common.service.PolicyAttributeService;
import com.jt.www.dao.mapper.endorse.EndorseMapper;
import com.jt.www.dao.mapper.risk.RiskInfoMapper;
import com.jt.www.dao.mapper.woxuebao.PayOutEntityMapper;
import com.jt.www.domain.enums.wxb.WxbAppStatusEnum;
import com.jt.www.domain.vo.PolEndorsementsInfoVO;
import com.jt.www.domain.vo.PolQueryForProDetailVO;
import com.jt.www.enums.ResultEnum;
import com.jt.www.enums.issue.*;
import com.jt.www.enums.woxuebao.PayOutStatusEnum;
import com.jt.www.model.entity.risk.RiskInfoEntity;
import com.jt.www.model.policyattribute.vo.PlicyClassVO;
import com.jt.www.model.remote.ins.InsResultVO;
import com.jt.www.model.remote.product.AreaQuery;
import com.jt.www.model.remote.product.ProdResultVo;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.reps.RemoteResultDTO;
import com.jt.www.model.reps.ResponseData;
import com.jt.www.model.woxuebao.PayOutEntity;
import com.jt.www.remote.PolClient;
import com.jt.www.remote.ProductClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.CommonUtils;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtil;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 开发环境redis不可用  所以先注释掉
 *
 * @author admin_ltf
 * @create 2019-05-09 14:21
 */
@Service
public class InsServiceImpl implements InsService {

    public static final Logger log = LoggerFactory.getLogger(InsServiceImpl.class);
    private static final String IS_DELETED = "isDeleted";
    private static final String PRODUCT_CODE = "productCode";
    @Autowired
    private InsClient insClient;
    @Autowired
    private ProductClient productClient;
    @Autowired
    private PolClient polClient;
    @Autowired
    private EndorseMapper endorseMapper;
    @Autowired
    private RiskInfoMapper riskInfoMapper;
    @Autowired
    private PayOutEntityMapper payOutEntityMapper;
    @Autowired
    private ExtendService extendService;
    @Autowired
    private PolicyAttributeService policyAttributeService;
    @Autowired
    private PayOutService payOutService;

    public ResponseData searchInsuranceList(String insParamVo) {

        Map<String, String> productList = null;
        try {
            productList = getProductList();
        } catch (Exception e) {
            e.printStackTrace();
            ResponseData responseData = new ResponseData();
            responseData.setCode(ResultEnum.ERROR_CODE_9999);
            responseData.setList(null);
            responseData.setMsg("远程获取产品列表失败");
            responseData.setData(null);
            responseData.setTotal(0);

            return responseData;
        }

        Map maps = (Map) JSON.parse(insParamVo);
        //保单号、学校名称、学生姓名、学生证件号码
        if (maps.get("diffName") != null) {
            String diffName = maps.get("diffName").toString().trim();
            if (StringUtils.isNotBlank(diffName)) {
                List<String> appCodeList = endorseMapper.selectEndorseByNameOrCardNo(diffName);
                if (appCodeList.size() <= 0) {
                    //返回一个空的集合
                    maps.put("appCodes", null);
                } else {
                    maps.put("appCodes", appCodeList);
                }
                maps.put("diffName", diffName);
            }
        }

        if (maps.get("riskTakerName") != null && maps.get("riskTakerCardNo") != null) {
            String riskTakerName = maps.get("riskTakerName").toString();
            String riskTakerCardNo = maps.get("riskTakerCardNo").toString();
            if (StringUtils.isNotBlank(riskTakerName) && StringUtils.isNotBlank(riskTakerCardNo)) {
                List<String> appCodeList = endorseMapper.selectEndorseByNameAndCardNo(riskTakerName, riskTakerCardNo);
                if (appCodeList.size() <= 0) {
                    //返回一个空的集合
                    maps.put("riskTakerAppCodes", null);
                } else {
                    maps.put("riskTakerAppCodes", appCodeList);
                }
            }
        }

        insParamVo = JSON.toJSONString(maps);

        ResponseData genericListResponseResponseEntity = null;
        try {
            genericListResponseResponseEntity = insClient.searchAppList(insParamVo);
        } catch (Exception e) {
            ResponseData responseData = new ResponseData();
            responseData.setCode(ResultEnum.ERROR_CODE_9999);
            responseData.setList(null);
            responseData.setMsg("远程获取保单列表失败");
            responseData.setData(null);
            responseData.setTotal(0);

            return responseData;
        }

        if (genericListResponseResponseEntity == null) {

            ResponseData responseData = new ResponseData();
            responseData.setCode(ResultEnum.ERROR_CODE_9999);
            responseData.setList(null);
            responseData.setMsg("远程获取保单列表失败");
            responseData.setData(null);
            responseData.setTotal(0);

            return responseData;
        }

        if (genericListResponseResponseEntity.getList() == null || genericListResponseResponseEntity.getList().size() <= 0) {
            ResponseData responseData = new ResponseData();
            responseData.setCode(ResultEnum.SUCCESS_CODE_0000);
            responseData.setList(null);
            responseData.setMsg("无查询数据");
            responseData.setData(null);
            responseData.setTotal(0);

            return responseData;
        }

        List<InsResultVO> list = (List<InsResultVO>) genericListResponseResponseEntity.getList();
        list = JSON.parseArray(JSON.toJSONString(list), InsResultVO.class);
        //long total = genericListResponseResponseEntity.getTotal();

        // 处理查询机构  添加前端需要的字段
        if (list != null && list.size() > 0) {
            genericListResponseResponseEntity.setList(handlerResultList(list, productList));
        }

        return genericListResponseResponseEntity;
    }

    private List<InsResultVO> handlerResultList(List<InsResultVO> list, Map<String, String> productMap) {

        for (InsResultVO insResultVO : list) {

            // TODO 拼装 ： 是否续保  和 续保时间倒计时。目前都是写成固定的，因为续保的逻辑还不确定。add by liangtengfei 0530
            //insResultVO.setIsRenewal(true);
            insResultVO.setRenewalTime("2");
            String productCode = insResultVO.getProductCode();

            // 拼装产品logo
            if (productMap != null) {
                String logo = productMap.get(productCode) == null ? "" : productMap.get(productCode);
                insResultVO.setLogo(logo);
            }

            //拼装险种信息 险种分为三大类，：riskTimeSlot_1-校责险;riskTimeSlot_2-实责险;riskTimeSlot_3-意外险;
            if (StringUtils.isNotBlank(insResultVO.getProductCode())) {
                Weekend<RiskInfoEntity> weekend = new Weekend<>(RiskInfoEntity.class);
                WeekendCriteria<RiskInfoEntity, Object> criteria = weekend.weekendCriteria();

                criteria.andEqualTo(IS_DELETED, false);
                criteria.andEqualTo(PRODUCT_CODE, insResultVO.getProductCode());

                List<RiskInfoEntity> riskEntities = riskInfoMapper.selectByExample(weekend);
                if (!CommonUtils.isEmpty(riskEntities)) {
                    insResultVO.setCategoryCode(riskEntities.get(0).getCategoryCode());
                    insResultVO.setCategoryName(riskEntities.get(0).getCategoryName());
                }
            }
            //济宁学平和徐州学平保险止期 特殊处理
            //济宁学平
            /*if("19PR979745".equals(insResultVO.getProductCode())
                    //徐州学平
                    || "19PR941489".equals(insResultVO.getProductCode())){
                String polEndDate = insResultVO.getPolEndDate().substring(0, 10) + " 00:00:00";
                insResultVO.setPolEndDate(polEndDate);
            }*/
        }

        //添加扩展信息
        extendService.setExtends(list, "00", false, false);

        return list;
    }

    public RemoteResultDTO searchWxbAppList(String insParamVo) {

        Map<String, String> productList = null;
        try {
            productList = getProductList();
        } catch (Exception e) {
            e.printStackTrace();
            return new RemoteResultDTO(ResultEnum.SERVER_ERROR, "远程获取产品列表失败");
        }

        Map maps = (Map) JSON.parse(insParamVo);

        if (maps.get("appStatus") != null) {
            String appStatus = maps.get("appStatus").toString();
            if (WxbAppStatusEnum.STATUS_00.getCode().equals(appStatus)) {
                String userCode = maps.get("userCode").toString();
                Weekend<PayOutEntity> weekend = Weekend.of(PayOutEntity.class);
                WeekendCriteria<PayOutEntity, Object> criteria = weekend.weekendCriteria();
                criteria.andEqualTo(PayOutEntity::getHolderCode, userCode);
                criteria.andEqualTo(PayOutEntity::getStatus, PayOutStatusEnum.DEFAULT.getCode());
                criteria.andGreaterThan(PayOutEntity::getPayOutTime, new Date());
                List<PayOutEntity> payOutEntities = payOutEntityMapper.selectByExample(weekend);
                if (payOutEntities != null && payOutEntities.size() > 0) {
                    List<String> appCodes = payOutEntities.stream()
                            .map(PayOutEntity::getApplicationFormCode)
                            .collect(Collectors.toList());

                    maps.put("appCodes", appCodes);
                } else {
                    return new RemoteResultDTO(ResultEnum.SUCCESS, null, 0L);
                }
            }
        }

        try {
            List<PlicyClassVO> policyAttributes = policyAttributeService.getProInfo("wxb", "2", "0");
            if (policyAttributes != null && policyAttributes.size() > 0) {
                maps.put("productType", policyAttributes.stream().map(PlicyClassVO::getCode).collect(Collectors.joining(",")));
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new RemoteResultDTO(ResultEnum.SERVER_ERROR, "教育后端获取产品编码失败");
        }

        insParamVo = JSON.toJSONString(maps);

        ResponseEntity<GenericListResponse<InsResultVO>> genericListResponseResponseEntity = null;
        try {
            genericListResponseResponseEntity = insClient.searchWxbAppList(insParamVo);
        } catch (Exception e) {
            return new RemoteResultDTO(ResultEnum.SERVER_ERROR, "远程获取保单列表失败");
        }

        if (genericListResponseResponseEntity == null) {

            return new RemoteResultDTO(ResultEnum.SERVER_ERROR, "远程获取保单列表失败");
        }


        GenericListResponse<InsResultVO> body = genericListResponseResponseEntity.getBody();

        List<InsResultVO> list = body.getList();
        long total = body.getTotal();

        // 处理查询机构  添加前端需要的字段
        if (list != null && list.size() > 0) {
            list = handlerWxbResultList(list, productList);
        }

        return new RemoteResultDTO(ResultEnum.SUCCESS, list, total);
    }

    private List<InsResultVO> handlerWxbResultList(List<InsResultVO> list, Map<String, String> productMap) {

        for (InsResultVO insResultVO : list) {

            // TODO 拼装 ： 是否续保  和 续保时间倒计时。目前都是写成固定的，因为续保的逻辑还不确定。add by liangtengfei 0530
            insResultVO.setRenewalTime("2");
            String productCode = insResultVO.getProductCode();

            // 拼装产品logo
            if (productMap != null) {
                String logo = productMap.get(productCode) == null ? "" : productMap.get(productCode);
                insResultVO.setLogo(logo);
            }

            // 设置投保单状态 (财务状态：00未到账/01已到账/02部分到账)
            // 1.00-待支付：未到账 且 支付超时时间 > 当前时间
            // 2.01-待起保：已到账 且 已出单 且 起期 > 当前日期
            // 3.02-保障中：(已出单 且 起期 < 当前时间 < 止期)  或 华泰两款产品（起期 < 当前时间 < 止期+15天）
            // 4.03-支付超时：未到账 且 当前时间 > 支付超时时间
            // 5.04-保单过期：已出单 且 当前时间 > 保险止期
            // 6.05-已退保：保单状态 = 01(已退保)
            // 7.08-待出单：已到账 且 出单标识 = N 且 投保单状态 = 08(待出单)
            // 8.09-出单失败：投保单状态 = 09(出单失败)
            Date polStartDate = DateUtils.str2Date(insResultVO.getPolStartDate(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
            Date polEndDate = DateUtils.str2Date(insResultVO.getPolEndDate(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
            Date currentDate = new Date();
            Date payOutDate = currentDate;

            //查询该投保单支付超时时间
            Weekend<PayOutEntity> weekend = Weekend.of(PayOutEntity.class);
            WeekendCriteria<PayOutEntity, Object> criteria = weekend.weekendCriteria();
            criteria.andEqualTo(PayOutEntity::getApplicationFormCode, insResultVO.getAppCode());
            List<PayOutEntity> payOutEntities = payOutEntityMapper.selectByExample(weekend);

            //todo 如果没有没时间添加
            if (!CollectionUtils.isEmpty(payOutEntities)) {
                payOutDate = payOutEntities.get(0).getPayOutTime();
            } else {
                PayOutEntity payOutEntity = createPayOut(insResultVO);
                payOutDate = payOutService.savePayOut(payOutEntity);
            }

            log.info("支付超时时间->{} , 当前系统时间->{}", payOutDate, currentDate);

            // 00-待支付
            if (FinanceStatusEnum.FS_00.getCode().equals(insResultVO.getFinanceStatus())
                    && (payOutDate.after(currentDate))) {

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_00.getCode());
                insResultVO.setPayOutTime(DateUtils.conver(payOutDate, DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));

            } else if (IssueStatusEnum.IS_Y.getCode().equals(insResultVO.getIssueStatus())
                    && (polStartDate.after(currentDate))
                    && PolicyStatusEnum.PS_02.getCode().equals(insResultVO.getPolicyStatus())) { // 01-待起保

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_01.getCode());

            } else if (IssueStatusEnum.IS_Y.getCode().equals(insResultVO.getIssueStatus())
                    && (currentDate.after(polStartDate))
                    && (polEndDate.after(currentDate))
                    && PolicyStatusEnum.PS_02.getCode().equals(insResultVO.getPolicyStatus())
                    || insResultVO.getIsRenewal()) { // 02-保障中

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_02.getCode());
                if (IssueEnum.CODE_4.getProCode().equals(insResultVO.getProductCode())
                        || IssueEnum.CODE_6.getProCode().equals(insResultVO.getProductCode())) {
                    insResultVO.setPolicyOverTime(DateUtils.conver(DateUtils.add(polEndDate, Calendar.DAY_OF_MONTH, 15), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
                } else {
                    insResultVO.setPolicyOverTime(DateUtils.conver(polEndDate, DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
                }

            } else if (FinanceStatusEnum.FS_00.getCode().equals(insResultVO.getFinanceStatus())
                    && (currentDate.after(payOutDate))
                    || AppStatusEnum.AS_11.getCode().equals(insResultVO.getAppStatus())) { // 03-支付超时

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_03.getCode());
                insResultVO.setPayOutTime(DateUtils.conver(payOutDate, DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));

            } else if (IssueStatusEnum.IS_Y.getCode().equals(insResultVO.getIssueStatus())
                    && PolicyStatusEnum.PS_02.getCode().equals(insResultVO.getPolicyStatus())
                    && (currentDate.after(polEndDate))) { // 04-保单过期

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_04.getCode());

            } else if (IssueStatusEnum.IS_Y.getCode().equals(insResultVO.getIssueStatus())
                    && PolicyStatusEnum.PS_00.getCode().equals(insResultVO.getPolicyStatus())) { // 05-已退保

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_05.getCode());
                //增加退保时间
                insResultVO.setCancelledTime("");
                //增加退保标识
                insResultVO.setCancelledFlag(false);
                try {
                    GenericDataResponse<PolQueryForProDetailVO> polResult = polClient.queryLiabilityPolDetail(insResultVO.getPolicyNo());
//                            ,"edu","edu");

                    if (polResult != null && "0000".equals(polResult.getCode()) && polResult.getData() != null) {

                        PolEndorsementsInfoVO endorsementsInfo = polResult.getData().getEndorsementsInfo();

                        if (endorsementsInfo != null) {
                            if (endorsementsInfo.getStartDate() != null) {
                                insResultVO.setCancelledTime(DateUtils.conver(endorsementsInfo.getStartDate(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));

                                if (endorsementsInfo.getStartDate().before(polStartDate)) {
                                    insResultVO.setCancelledFlag(true);
                                }
                            }
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (FinanceStatusEnum.FS_01.getCode().equals(insResultVO.getFinanceStatus())
                    && IssueStatusEnum.IS_N.getCode().equals(insResultVO.getIssueStatus())
                    && AppStatusEnum.AS_08.getCode().equals(insResultVO.getAppStatus())) { // 08-待出单

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_08.getCode());

            } else if (AppStatusEnum.AS_09.getCode().equals(insResultVO.getAppStatus())) { // 09-出单失败

                insResultVO.setAppStatus(WxbAppStatusEnum.STATUS_09.getCode());
            }
        }

        return list;
    }

    private PayOutEntity createPayOut(InsResultVO insResultVO) {
        PayOutEntity payOutEntity = new PayOutEntity();

        payOutEntity.setApplicationFormCode(insResultVO.getAppCode());
        payOutEntity.setCreateTime(DateUtils.str2Date(insResultVO.getApplicationDate(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
        payOutEntity.setProductCode(insResultVO.getProductCode());
        payOutEntity.setStartTime(DateUtils.str2Date(insResultVO.getPolStartDate(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
        payOutEntity.setStatus(PayOutStatusEnum.DEFAULT.getCode());
        payOutEntity.setIsRenewal(insResultVO.getRenewal());
        payOutEntity.setHolderCode(insResultVO.getHolderCode());
        return payOutEntity;
    }

    public Map<String, String> getProductList() throws Exception {
//        Map<String,String> map = (Map<String,String>)redisTemplate.opsForValue().get(redis_key);
//        if(map == null){
        Map<String, String> map = new HashMap<String, String>();
        ResponseEntity<GenericListResponse<ProdResultVo>> genericListResponseResponseEntity = null;
        List areaCodeList = new ArrayList<>();
        areaCodeList.add("000000");
        List clientNoList = new ArrayList<>();
        clientNoList.add("pcedu");

        // 和前端沟通  是固定参数
        AreaQuery areaQuery = new AreaQuery();
        areaQuery.setPs(1000);
        areaQuery.setAreaCodeList(areaCodeList);
        areaQuery.setClientNoList(clientNoList);
        genericListResponseResponseEntity = productClient.searchProductList("edu", areaQuery);

        GenericListResponse<ProdResultVo> body = genericListResponseResponseEntity.getBody();

        List<ProdResultVo> list = body.getList();

        map = new HashMap<String, String>();
        for (ProdResultVo prodResultVo : list) {
            map.put(prodResultVo.getCode(), prodResultVo.getLogo());
        }
//            redisTemplate.opsForValue().set(redis_key,map,5,TimeUnit.MINUTES);
//        }

        return map;
    }

    @Override
    public ResponseEntity countAppNumByStatus(String userCode) throws Exception {

        Map<String, Object> map = new HashMap<>();

        Map<String, Object> param = new HashMap<>();
        param.put("pn", 1);
        param.put("ps", 10);
        param.put("userCode", userCode);
        param.put("source", "");
        param.put("channelCode", "edu");
        param.put("channelType", "02,0001");
        try {
            List<PlicyClassVO> policyAttributes = policyAttributeService.getProInfo("wxb", "2", "0");
            if (policyAttributes != null && policyAttributes.size() > 0) {
                param.put("productType", policyAttributes.stream().map(PlicyClassVO::getCode).collect(Collectors.joining(",")));
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.info("获取待支付/保障中保单数量 查询产品编码信息时 异常 userCode{}", userCode);
            map.put("00", 0);
            map.put("02", 0);
            return GenericDataResponse.okWithData(map);
        }

        // 统计保障中数量
        param.put("appStatus", WxbAppStatusEnum.STATUS_02.getCode());
        param.put("name", "");

        ResponseEntity<GenericListResponse<InsResultVO>> result = insClient.searchWxbAppList(JsonUtil.object2Json(param));

        if (result != null && result.getBody() != null) {
            map.put("02", result.getBody().getTotal());
        } else {
            map.put("02", 0);
        }

        // 统计待支付数量
        Weekend<PayOutEntity> weekend = Weekend.of(PayOutEntity.class);
        WeekendCriteria<PayOutEntity, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(PayOutEntity::getHolderCode, userCode);
        criteria.andEqualTo(PayOutEntity::getStatus, PayOutStatusEnum.DEFAULT.getCode());
        criteria.andGreaterThan(PayOutEntity::getPayOutTime, new Date());
        List<PayOutEntity> payOutEntities = payOutEntityMapper.selectByExample(weekend);
        if (payOutEntities != null && payOutEntities.size() > 0) {
            List<String> appCodes = payOutEntities.stream()
                    .map(PayOutEntity::getApplicationFormCode)
                    .collect(Collectors.toList());

            param.put("appCodes", appCodes);
        }
        param.put("appStatus", WxbAppStatusEnum.STATUS_00.getCode());
        param.put("name", "");

        ResponseEntity<GenericListResponse<InsResultVO>> responseEntity = insClient.searchWxbAppList(JsonUtil.object2Json(param));

        if (responseEntity != null && responseEntity.getBody() != null) {
            map.put("00", responseEntity.getBody().getTotal());
        } else {
            map.put("00", 0);
        }

        // 待起保数量
        param.put("appStatus", WxbAppStatusEnum.STATUS_01.getCode());
        param.put("name", "");

        ResponseEntity<GenericListResponse<InsResultVO>> result2 = insClient.searchWxbAppList(JsonUtil.object2Json(param));

        if (result2 != null && result2.getBody() != null) {
            map.put("01", result2.getBody().getTotal());
        } else {
            map.put("01", 0);
        }

        return GenericDataResponse.okWithData(map);
    }
}
